using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace TidhiGanitam.DataModel
{
    public class NakshatramuRoutineItem
    {
        private int m_Year;
        DateTime m_Date;
        private int m_SNo;
        ArrayList m_RaviRoutines;
        ArrayList m_ChandraRoutines;
        ArrayList m_DinamuRoutines;
        ArrayList m_NakshatramuDetails;
        Rasi m_NakshatramuTime;
        double m_CurrentNakshatramu;
        Enums.TidhiState m_PreviousNakshatramuState;
        bool m_CheckingForEshyam;

        public int Bhagam
        {
            get { return m_SNo; }
        }

        public DateTime Date
        {
            get { return m_Date; }
        }
        public Rasi NakshatramuTime
        {
            get { return m_NakshatramuTime; }
        }
        public ArrayList NakshatramuDetails
        {
            get
            { return m_NakshatramuDetails; }
            set
            {
                m_NakshatramuDetails = value;
            }
        }
        public double CurrentNakshatramu
        {
            get
            { return m_CurrentNakshatramu; }
            set
            { m_CurrentNakshatramu = value; }

        }
        public Enums.TidhiState PreviousNakshatramuState
        {
            get
            { return m_PreviousNakshatramuState; }
        }
        public NakshatramuRoutineItem(int SNo, int Year, DateTime Date, double currentNakshatramu,
            Enums.TidhiState previousNakshatramuState, ArrayList RaviRoutines,
            ArrayList ChandraRoutines, ArrayList DinamuRoutines)
        {
            m_SNo = SNo;
            m_Year = Year;
            m_Date = Date;
            m_NakshatramuDetails = new ArrayList();
            m_CurrentNakshatramu = currentNakshatramu;
            m_PreviousNakshatramuState = previousNakshatramuState;
            m_RaviRoutines = RaviRoutines;
            m_ChandraRoutines = ChandraRoutines;
            m_DinamuRoutines = DinamuRoutines;
            m_NakshatramuTime = new Rasi();
        }
        public void Calculate(bool CheckingForEshyam, NakshatramuRoutineItem PreviousNakshatramuRoutine, DinamuRoutineItem PreviousDinamu)
        {
            m_CheckingForEshyam = CheckingForEshyam;
            double dSign = 1;
            Rasi SpastaChandra = new Rasi(((ChandraRoutineItem)m_ChandraRoutines[m_SNo]).SpastaChandrudu);
            Rasi SpastaRavi = new Rasi(((RaviRoutineItem)m_RaviRoutines[m_SNo]).MadyamaRavi);
            Rasi SpastaChandraGati = new Rasi(((ChandraRoutineItem)m_ChandraRoutines[m_SNo]).ChandraDinaGatiPhalam);
            Rasi SpastaRaviGati = new Rasi(((RaviRoutineItem)m_RaviRoutines[m_SNo]).Gati);
            DinamuRoutineItem CurrentDinamu = (DinamuRoutineItem)m_DinamuRoutines[m_SNo];

            #region Nakshatramu calculation
            // 1. Find Starting Nakshatramu
            Double dNakshatramuIndex = MathHelper.GetDegrees(((Rasi)(SpastaChandra / Constants.NakshatraPramanam)).RawValue);
            if (m_SNo == 0 && !CheckingForEshyam)
            {
                m_CurrentNakshatramu = dNakshatramuIndex;
            }
            // 4. Find Advancement
            Rasi NakshatramuAdvancement = SpastaChandra - (Constants.NakshatraPramanam * dNakshatramuIndex);
            Rasi NakshatramuRemining = new Rasi(NakshatramuAdvancement);
            // 5. If Advancement is more than 1/4 of Nakshatramu(0-3-20), subtract from 13-20; Sign here is Add
            //      Else we dont have to subtract from 13-20; Sign will be Subtract : -1

            // Note: Here we may have to do some adjustments as when previous Nakshatramu is purti, we need not check
            // whether curernt Nakshatramu advancement is more than quarter Nakshatramu.
            if (NakshatramuAdvancement >= Constants.NakshatraPadaPramanam && (m_PreviousNakshatramuState != Enums.TidhiState.Purti) &&
                (m_PreviousNakshatramuState != Enums.TidhiState.NextdayEshyamAdjustment))
            {
                NakshatramuRemining = Constants.NakshatraPramanam - NakshatramuAdvancement;
            }
            else
            {
                Rasi CurNakInPrvDay = new Rasi();
                Rasi CurNakInCrrDay = new Rasi();
                Rasi TotalNak = new Rasi();

                if (m_PreviousNakshatramuState != Enums.TidhiState.Purti)
                {
                    CurNakInPrvDay = PreviousDinamu.RojuPramanam - PreviousNakshatramuRoutine.NakshatramuTime;
                }
                else
                {
                    CurNakInPrvDay = PreviousDinamu.RojuPramanam;
                }
                CurNakInCrrDay = new Rasi(NakshatramuRemining / SpastaChandraGati);
                TotalNak = CurNakInPrvDay + CurNakInCrrDay;
                if (TotalNak < new Rasi(0, 0, 35))//|| CurNakInCrrDay > CurrentDinamu.Dinardhamu
                {
                    NakshatramuRemining = Constants.NakshatraPramanam - NakshatramuAdvancement;
                }
                else
                {
                    dSign = -1;
                    //we have to be careful here. sometimes if the Nakshatramutime is greater than the dinardhamu,
                    //m_NakshatramuTime will be -ve. 
                }
            }
            //Another adjustment is if when Nakshatramu

            // 6. Divide Nakshatramu remining with Gati sum
            Rasi NakshatramuTime = NakshatramuRemining / SpastaChandraGati;

            // 7. Add this to dinardham. We consider the sign here
            m_NakshatramuTime = ((DinamuRoutineItem)m_DinamuRoutines[m_SNo]).Dinardhamu + (NakshatramuTime * dSign);

            //Just check nakshatramu time is -ve, make it +ve value
            if (m_NakshatramuTime < new Rasi(0, 0, 0))
            {
                m_NakshatramuTime = new Rasi(m_NakshatramuTime * -1); //just to make the value +ve
            }

            //Some times if the 


            // if the
            if (m_CurrentNakshatramu < 0)
            {
                m_CurrentNakshatramu = dNakshatramuIndex;
            }

            // 8. Find out if Nakshatramu spans entire day
            if (m_NakshatramuTime > CurrentDinamu.RojuPramanam)
            {
                if (!CheckingForEshyam)
                {
                    m_NakshatramuTime = new Rasi(CurrentDinamu.RojuPramanam);
                    NakshatramuDetails PurtiNakshatramu = new NakshatramuDetails(m_CurrentNakshatramu, Enums.TidhiState.Purti, m_Date, CurrentDinamu.RojuPramanam, CalculateTotalSpan(PreviousNakshatramuRoutine));
                    m_NakshatramuDetails.Add(PurtiNakshatramu);
                    m_PreviousNakshatramuState = Enums.TidhiState.Purti;
                }
            }
            else
            {
                //9. Nakshatramu completed. add this Nakshatramu to arraylist
                NakshatramuDetails NormalNakshatramu = new NakshatramuDetails(m_CurrentNakshatramu, Enums.TidhiState.Ending, m_Date, new Rasi(m_NakshatramuTime), CalculateTotalSpan(PreviousNakshatramuRoutine));
                m_NakshatramuDetails.Add(NormalNakshatramu);
                m_PreviousNakshatramuState = Enums.TidhiState.Ending;
                // Increment the tidhi and masamu
                if (m_SNo == 0 && !CheckingForEshyam)
                {
                    if (m_NakshatramuTime > CurrentDinamu.Dinardhamu)
                    {
                        IncrementNakshatramu();
                    }
                }
                else
                {
                    IncrementNakshatramu();
                }
                // 9. Find out if Eshyam is present
                Rasi StartNakshatramuTimeSpan = CurrentDinamu.RojuPramanam - m_NakshatramuTime;
                if (!CheckingForEshyam)
                {
                    if (CheckForEshyam(m_SNo, StartNakshatramuTimeSpan, CurrentNakshatramu, m_PreviousNakshatramuState))
                    {
                        Rasi EsyamNakshatramuTime = Constants.NakshatraPramanam / SpastaChandraGati;
                        if (EsyamNakshatramuTime < StartNakshatramuTimeSpan)
                        {
                            m_NakshatramuTime = new Rasi(EsyamNakshatramuTime);
                            NakshatramuDetails EshyamNakshatramu = new NakshatramuDetails(m_CurrentNakshatramu, Enums.TidhiState.Eshyam, m_Date, new Rasi(m_NakshatramuTime), new Rasi(m_NakshatramuTime));
                            m_NakshatramuDetails.Add(EshyamNakshatramu);
                            m_PreviousNakshatramuState = Enums.TidhiState.Eshyam;
                            // Increment the tidhi and masamu
                            IncrementNakshatramu();
                        }
                        else
                        {
                            m_PreviousNakshatramuState = Enums.TidhiState.NextdayEshyamAdjustment;
                        }
                    }
                }
            }
            #endregion


        }

        private Rasi CalculateTotalSpan(NakshatramuRoutineItem PreviousNakshatramuRoutine)
        {
            if (!m_CheckingForEshyam)
            {
                m_CheckingForEshyam = m_CheckingForEshyam;
            }
            Rasi NakshatramuSpan = new Rasi();
            Rasi PrevDayRojuPramanam;
            if(m_SNo > 0)
            {
                PrevDayRojuPramanam = ((DinamuRoutineItem)m_DinamuRoutines[PreviousNakshatramuRoutine.Bhagam]).RojuPramanam;
            }
            else
            {
                PrevDayRojuPramanam = ((DinamuRoutineItem)m_DinamuRoutines[m_SNo]).RojuPramanam;
                NakshatramuSpan = PrevDayRojuPramanam; //we dont have any data. so setting as rojupramanam
            }

            foreach (NakshatramuDetails nakshatramu in PreviousNakshatramuRoutine.NakshatramuDetails)
            {
                NakshatramuSpan += nakshatramu.EndTime;
            }
            Rasi NakshatramuInPreviousDay = PrevDayRojuPramanam - NakshatramuSpan;
            Rasi TotalSpan = new Rasi();
            if (PreviousNakshatramuRoutine.PreviousNakshatramuState == Enums.TidhiState.Purti)
            {
                TotalSpan = ((NakshatramuDetails)PreviousNakshatramuRoutine.NakshatramuDetails[0]).TotalSpan + m_NakshatramuTime;
                ((NakshatramuDetails)PreviousNakshatramuRoutine.NakshatramuDetails[0]).TotalSpan = TotalSpan;
            }
            else
            {
                TotalSpan = NakshatramuInPreviousDay + m_NakshatramuTime;
            }
            return TotalSpan;
        }

        private void IncrementNakshatramu()
        {
            m_CurrentNakshatramu++; //Nakshatramu completed. so increment the Nakshatramu
            m_CurrentNakshatramu = m_CurrentNakshatramu % 27;
        }
        private bool CheckForEshyam(int CurrentPadakam, Rasi CurrentTime, double CurrentNakshatramu, Enums.TidhiState PreviousNakshatramuState)
        {
            bool RetValue = false;

            NakshatramuRoutineItem NextItem = new NakshatramuRoutineItem(CurrentPadakam + 1, m_Year, m_Date.AddDays(1), CurrentNakshatramu, PreviousNakshatramuState,
                m_RaviRoutines, m_ChandraRoutines, m_DinamuRoutines);
            NextItem.Calculate(true, this, (DinamuRoutineItem)m_DinamuRoutines[CurrentPadakam]);
            Rasi EndTime = new Rasi(NextItem.NakshatramuTime);
            if ((CurrentTime + EndTime) > new Rasi(0, 1, 30, 0))
            {
                RetValue = true;
            }
            return RetValue;
        }
    }
}
